//输入序列状态检测机

// 该模块实现一个Moore型有限状态机，用于检测连续输入位流中是否包含特定的二进制模
// 式“1101”。一旦识别到该序列，dout 输出为1。该设计是控制逻辑中的常见场景，类似于
// CPU 中的指令译码检测。实现一个Moore型状态机，检测输入序列中是否出现“1101”子
// 串：

//定义五个状态
// S0:初始状态
// S1:检测到1
// S2:检测到11
// S3:检测到110
// S4:检测到1101

//1、初始时，默认为S0初始状态
//2、在S0状态，检测到1进入S1状态，否则回到S0状态
//3、在S1状态，检测到1进入S2状态，否则回到S0状态
//4、在S2状态，检测到0进入S3状态，否则回到S2状态
//5、在S3状态，检测到1进入S4状态，否则回到S0状态
//6、在S4状态，输出1，检测成功，其他状态时输出0， 此时再检测到1进入S2状态，检测到0回到S0状态


module fsm_detector(
    input wire clk, //时钟信号
    input wire rst, //复位信号
    input wire din, //输入信号
    output wire dout //输出信号
);

//表示五个状态需要至少三个二进制位
    parameter S0 = 3'b000;
    parameter S1 = 3'b001;
    parameter S2 = 3'b010;
    parameter S3 = 3'b011;
    parameter S4 = 3'b100;

    reg[2:0] state; //当前状态
    reg[2:0] next_state; //下一个状态

    always@(posedge clk or posedge rst) begin
        if(rst) begin
        //复位
            state <= S0;
        end
        else begin
            state <= next_state;
        end
    end


    //确定下一个状态的逻辑
    always@(*) begin
        case (state)
            S0:
            begin
                if(din == 1'b1) begin
                    next_state = S1;
                end
                else begin
                    next_state = S0;
                end
            end

            S1:
            begin
                if(din == 1'b1) begin
                    next_state = S2;
                end
                else begin
                    next_state = S0;
                end

            end

            S2:
            begin
                if(din == 1'b0) begin
                    next_state = S3;
                end
                else begin
                    next_state = S2;
                end

            end

            S3:
            begin
                if(din == 1'b1) begin
                    next_state = S4;
                end
                else begin
                    next_state = S0;
                end

            end

            S4:
            begin
                if(din == 1'b1) begin
                    next_state = S2;
                end
                else begin
                    next_state = S0;
                end
            end

            default:
            begin
                next_state = S0;
            end
        endcase

    end

    assign dout = (state == S4) ? 1'b1 : 1'b0;
endmodule


//测试文件
//testbench of fsm_detector
`timescale 1ns/100ps
module fsm_detector_tb;
    reg clk;
    reg rst;
    reg din;
    wire dout;

    fsm_detector uut(
        .clk(clk),
        .rst(rst),
        .din(din),
        .dout(dout)
    );

    //生成时钟信号
    initial begin
        clk = 0;
        forever begin
            #5 clk = ~clk;
        end
    end

    //监控信号 观察输出
    initial begin
    $monitor("Time: %0t, rst: %b, din: %b, state: %b, dout: %b", $time, rst, din, uut.state, dout);
    end

    initial begin
        rst = 1;//复位信号 逻辑1有效
        din = 0;
    #10 rst = 0;
        din = 0;
    #10 din = 1;
    #10 din = 0;
    #10 din = 1; //1
    #10 din = 1; //1
    #10 din = 0; //0
    #10 din = 1; //1
    #10 din = 0;
    #10 $stop;
    end

endmodule